package daos

import (
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"sanrenx.com/xyxf/app/models"
	"sanrenx.com/xyxf/pkg/orm"
	"strconv"
)

/**
 * @Description:文章
 */
type MusicDao struct {
	DB *gorm.DB
}

/**
 * @Description: 根据类型获取分类下歌单 数量
 * @receiver dao
 * @param categoryIds 分类ID数组
 * @param exclude 是否排除
 * @return count 数量
 * @return err 异常信息
 */
func (dao *MusicDao) GetPlaylistCountByMode2Category(mode *string, cpIds []int, exclude bool) (count int64, err error) {
	tx := dao.DB.Table("playlist").
		Select([]string{
			"id",
		})

	isNotAll := true //是否分类0：查询全部分类
	for _, cId := range cpIds {
		if cId == 0 {
			isNotAll = false
			break
		}
	}

	// 非全部
	if isNotAll {
		//获取子分类
		categoryDao := CategoryDao{orm.DB}
		categoryIds, cErr := categoryDao.GetCategoryIdsByPid(cpIds)
		if cErr != nil {
			return 0, cErr
		}

		idsCount := len(categoryIds) //分类数量
		if idsCount > 0 {
			if exclude { //排除
				tx = tx.Where("category_id NOT IN ?", categoryIds)
			} else {
				if idsCount == 1 {
					tx = tx.Where("category_id = ?", categoryIds[0])
				} else {
					tx = tx.Where("category_id IN ?", categoryIds)
				}
			}
		} else {
			return 0, nil
		}
	}

	//歌单类型
	if mode != nil {
		tx.Where("mode = ?", mode) //歌单类型
	}

	if err = tx.Where("deleted_at is NUll").Count(&count).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return 0, err
	}

	return count, nil
}

/**
 * @Description: 根据类型获取分类下歌单
 * @receiver dao
 * @param offset 起始
 * @param size 数量
 * @param categoryIds 分类ID数组
 * @param exclude 排除
 * @param orderBy 排序
 * @return ids 文章ID数组
 * @return list 文章column数组
 * @return err 异常信息
 */
func (dao *MusicDao) GetPagePlaylistColumnByMode2Category(offset int, size int, mode *string, cpIds []int, exclude bool, orderBy string) (ids []string, list []*orm.Column, err error) {
	tx := dao.DB.Table("playlist").
		Select([]string{
			"id",
			"hot",
			"created_at",
		})

	isNotAll := true //是否分类0：查询全部分类
	for _, cId := range cpIds {
		if cId == 0 {
			isNotAll = false
			break
		}
	}
	// 非全部
	if isNotAll {
		//获取子分类
		categoryDao := CategoryDao{orm.DB}
		categoryIds, cErr := categoryDao.GetCategoryIdsByPid(cpIds)
		if cErr != nil {
			return nil, nil, cErr
		}

		idsCount := len(categoryIds) //分类数量
		if idsCount > 0 {
			if exclude { //排除
				tx = tx.Where("category_id NOT IN ?", categoryIds)
			} else {
				if idsCount == 1 {
					tx = tx.Where("category_id = ?", categoryIds[0])
				} else {
					tx = tx.Where("category_id IN ?", categoryIds)
				}
			}
		} else {
			return nil, nil, nil
		}
	}

	order := orm.OrderByNewDesc
	if orderBy == "hot" {
		order = orm.OrderByHotDesc
	}

	//歌单类型
	if mode != nil {
		tx.Where("mode = ?", mode) //歌单类型
	}

	if err = tx.Where("deleted_at is NUll"). //未删除
							Order(order).
							Offset(offset).
							Limit(size).
							Find(&list).
							Error; err != nil && err != gorm.ErrRecordNotFound {
		return nil, nil, err
	}

	//提出IDs
	for _, item := range list {
		ids = append(ids, strconv.FormatUint(item.ID, 10))
	}

	return ids, list, nil
}

/**
 * @Description: 歌单收录音乐数量
 * @receiver dao
 * @param id 歌单ID
 * @return count 音乐数量
 * @return err 异常信息
 */
func (dao *MusicDao) GetAudioCountByPlaylist(id uint64) (count int64, err error) {

	//获取专辑文章IDs
	if err = dao.DB.Table("playlist_audio").
		Select("audio_id").
		Where("deleted_at is NULL").
		Where("playlist_id = ?", id).
		Count(&count).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return 0, err
	}

	return count, nil
}

/**
 * @Description: 获取歌单详情及关联音乐
 * @receiver dao
 * @param id 歌单ID
 * @return ids 歌单音乐ID数组
 * @return err 异常信息
 */
func (dao *MusicDao) GetPageAudioColumnByPlaylist(offset int, size int, playlistID uint64, orderBy string) (ids []string, list []*orm.Column, err error) {

	tx := dao.DB.Table("playlist_audio as playlist").
		Select([]string{
			"id",
			"hot",
			"created_at",
		})

	//如果指定歌单
	if playlistID > 0 {
		tx.Joins("inner join audio on audio.id=playlist.audio_id").
			Where("audio.deleted_at is NULL")
	}

	//排序方式
	order := orm.OrderByNewDesc
	if orderBy == "hot" {
		order = orm.OrderByHotDesc
	}

	//获取歌单音乐IDs
	if err = tx.Where("playlist.deleted_at is NUll").
		Where("playlist.playlist_id = ?", playlistID). //未删除
		Order(order).
		Offset(offset).
		Limit(size).
		Find(&list).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return nil, nil, err
	}

	//提出IDs
	for _, item := range list {
		ids = append(ids, strconv.FormatUint(item.ID, 10))
	}

	return ids, list, nil
}

/**
 * @Description: 音乐数量
 * @receiver dao
 * @param keyman 人物ID
 * @return count 音乐数量
 * @return err 异常信息
 */
func (dao *MusicDao) GetAudioCountByKeyman(keymanIds []int, exclude bool) (count int64, err error) {

	tx := dao.DB.Table("audio").
		Select([]string{
			"id",
		})

	isNotAll := true //是否分类0：查询全部分类
	for _, cId := range keymanIds {
		if cId == 0 {
			isNotAll = false
			break
		}
	}
	// 非全部
	if isNotAll {
		idsCount := len(keymanIds) //分类数量
		if idsCount > 0 {
			if exclude { //排除
				tx = tx.Where("keyman_id NOT IN ?", keymanIds)
			} else {
				if idsCount == 1 {
					tx = tx.Where("keyman_id = ?", keymanIds[0])
				} else {
					tx = tx.Where("keyman_id IN ?", keymanIds)
				}
			}
		} else {
			return 0, nil
		}
	}

	if err = tx.Where("deleted_at is NUll").Count(&count).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return 0, err
	}

	return count, nil
}

/**
 * @Description: 获取人物音乐列表
 * @receiver dao
 * @param keyman 人物ID
 * @return ids 歌单音乐ID数组
 * @return err 异常信息
 */
func (dao *MusicDao) GetPageAudioColumnByKeyman(offset int, size int, keymanIds []int, exclude bool, orderBy string) (ids []string, list []*orm.Column, err error) {

	tx := dao.DB.Table("audio").
		Select([]string{
			"id",
			"hot",
			"created_at",
		})

	isNotAll := true //是否分类0：查询全部分类
	for _, cId := range keymanIds {
		if cId == 0 {
			isNotAll = false
			break
		}
	}
	// 非全部
	if isNotAll {
		idsCount := len(keymanIds) //分类数量
		if idsCount > 0 {
			if exclude { //排除
				tx = tx.Where("keyman_id NOT IN ?", keymanIds)
			} else {
				if idsCount == 1 {
					tx = tx.Where("keyman_id = ?", keymanIds[0])
				} else {
					tx = tx.Where("keyman_id IN ?", keymanIds)
				}
			}
		} else {
			return nil, nil, nil
		}
	}

	//排序方式
	order := orm.OrderByNewDesc
	if orderBy == "hot" {
		order = orm.OrderByHotDesc
	}

	//获取歌单音乐IDs
	if err = tx.Where("deleted_at is NUll").
		Order(order).
		Offset(offset).
		Limit(size).
		Find(&list).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return nil, nil, err
	}

	//提出IDs
	for _, item := range list {
		ids = append(ids, strconv.FormatUint(item.ID, 10))
	}

	return ids, list, nil
}

/**
 * @Description: 歌单详情
 * @receiver dao
 * @param id 歌单ID
 * @return data 歌单
 * @return err 异常信息
 */
func (dao *MusicDao) GetPlaylist(id uint64) (*models.PlaylistDetails, error) {
	//文章模型
	var data models.PlaylistDetails
	// 查询数据
	if err := dao.DB.Unscoped().
		Table("playlist").
		Preload(clause.Associations). //预加载全部关联
		Where("id = ?", id).
		First(&data).
		Error; err != nil {
		//无数据
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}

	return &data, nil
}

/**
 * @Description: 音乐详情
 * @receiver dao
 * @param id 音乐ID
 * @return data 歌单
 * @return err 异常信息
 */
func (dao *MusicDao) GetAudio(id uint64) (*models.AudioDetails, error) {
	//文章模型
	var data models.AudioDetails
	// 查询数据
	if err := dao.DB.Unscoped().
		Table("audio").
		Preload(clause.Associations). //预加载全部关联
		Where("id = ?", id).
		First(&data).
		Error; err != nil {
		//无数据
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}

	return &data, nil
}
